//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package dataview_chat_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas-org/api-server/api_common"
	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/dataview_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/user_dao"
	"atomgit.com/openlinksaas-org/api-server/utils"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/dataview_chat_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/notices/notices_dataview"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

type DataViewChatApiImpl struct {
	dataview_chat_api.UnimplementedDataViewChatApiServer
}

func (apiImpl *DataViewChatApiImpl) SendMsg(ctx context.Context, req *dataview_chat_api.SendMsgRequest) (*dataview_chat_api.SendMsgResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &dataview_chat_api.SendMsgResponse{
			Code:   dataview_chat_api.SendMsgResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &dataview_chat_api.SendMsgResponse{
			Code:   dataview_chat_api.SendMsgResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &dataview_chat_api.SendMsgResponse{
			Code:   dataview_chat_api.SendMsgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &dataview_chat_api.SendMsgResponse{
			Code:   dataview_chat_api.SendMsgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := dataview_dao.ViewDao.Exist(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &dataview_chat_api.SendMsgResponse{
			Code:   dataview_chat_api.SendMsgResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}

	msgId := uuid.NewString()
	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = dataview_dao.ChatMsgIndexDao.Insert(sessCtx, &dataview_dao.ChatMsgIndexDbItem{
			MsgId:     msgId,
			ViewId:    req.ViewId,
			TimeStamp: nowTime,
		})
		if err != nil {
			return nil, err
		}
		err = dao.MsgDataDao.Insert(sessCtx, &dao.MsgDataDBItem{
			MsgId:        msgId,
			Content:      req.Content,
			CreateUserId: sessionItem.UserId,
			CreateTime:   nowTime,
			HasChanged:   false,
		})
		if err != nil {
			return nil, err
		}
		return &dataview_chat_api.SendMsgResponse{
			Code:  dataview_chat_api.SendMsgResponse_CODE_OK,
			MsgId: msgId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.NewChatMsgNotice{
		ProjectId:  req.ProjectId,
		ViewId:     req.ViewId,
		MsgId:      msgId,
		SendUserId: sessionItem.UserId,
	})
	return ret.(*dataview_chat_api.SendMsgResponse), nil
}

func (apiImpl *DataViewChatApiImpl) ListMsg(ctx context.Context, req *dataview_chat_api.ListMsgRequest) (*dataview_chat_api.ListMsgResponse, error) {
	emptyList := []*dataview_chat_api.ChatMsgInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &dataview_chat_api.ListMsgResponse{
			Code:    dataview_chat_api.ListMsgResponse_CODE_WRONG_SESSION,
			ErrMsg:  "会话不存在",
			MsgList: emptyList,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &dataview_chat_api.ListMsgResponse{
			Code:    dataview_chat_api.ListMsgResponse_CODE_NO_PROJECT,
			ErrMsg:  "项目不存在",
			MsgList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &dataview_chat_api.ListMsgResponse{
			Code:    dataview_chat_api.ListMsgResponse_CODE_NO_PERMISSION,
			ErrMsg:  "没有权限",
			MsgList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}
	exist, err := dataview_dao.ViewDao.Exist(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &dataview_chat_api.ListMsgResponse{
			Code:    dataview_chat_api.ListMsgResponse_CODE_NO_VIEW,
			ErrMsg:  "数据视图不存在",
			MsgList: emptyList,
		}, nil
	}

	lastMsgId, err := dataview_dao.ChatMsgIndexDao.GetListMsgId(ctx, req.ViewId)
	if err != nil {
		return nil, err
	}

	indexItemList, err := dataview_dao.ChatMsgIndexDao.List(ctx, req.ViewId, req.ListType, req.ListRefTime, int64(req.Limit))
	if err != nil {
		return nil, err
	}
	msgIdList := []string{}
	for _, indexItem := range indexItemList {
		msgIdList = append(msgIdList, indexItem.MsgId)
	}

	msgItemList, err := dao.MsgDataDao.ListById(ctx, msgIdList)
	if err != nil {
		return nil, err
	}
	msgItemMap := map[string]*dao.MsgDataDBItem{}
	userIdList := []string{}
	for _, msgItem := range msgItemList {
		msgItemMap[msgItem.MsgId] = msgItem
		userIdList = append(userIdList, msgItem.CreateUserId)
	}
	//获取用户信息
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}
	//生成结果
	msgList := []*dataview_chat_api.ChatMsgInfo{}
	for _, indexItem := range indexItemList {
		msgItem, ok := msgItemMap[indexItem.MsgId]
		if !ok {
			continue
		}
		msg := &dataview_chat_api.ChatMsgInfo{
			MsgId:      msgItem.MsgId,
			Content:    msgItem.Content,
			SendUserId: msgItem.CreateUserId,
			SendTime:   msgItem.CreateTime,
			HasChanged: msgItem.HasChanged,
		}
		userItem, ok := userItemMap[msgItem.CreateUserId]
		if ok {
			msg.SendDisplayName = userItem.BasicInfo.DisplayName
			msg.SendLogoUri = userItem.BasicInfo.LogoUri
		}
		msgList = append(msgList, msg)
	}

	return &dataview_chat_api.ListMsgResponse{
		Code:      dataview_chat_api.ListMsgResponse_CODE_OK,
		MsgList:   msgList,
		LastMsgId: lastMsgId,
	}, nil
}

func (apiImpl *DataViewChatApiImpl) UpdateMsg(ctx context.Context, req *dataview_chat_api.UpdateMsgRequest) (*dataview_chat_api.UpdateMsgResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &dataview_chat_api.UpdateMsgResponse{
			Code:   dataview_chat_api.UpdateMsgResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &dataview_chat_api.UpdateMsgResponse{
			Code:   dataview_chat_api.UpdateMsgResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &dataview_chat_api.UpdateMsgResponse{
			Code:   dataview_chat_api.UpdateMsgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &dataview_chat_api.UpdateMsgResponse{
			Code:   dataview_chat_api.UpdateMsgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := dataview_dao.ViewDao.Exist(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &dataview_chat_api.UpdateMsgResponse{
			Code:   dataview_chat_api.UpdateMsgResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}
	exist, err = dataview_dao.ChatMsgIndexDao.Exist(ctx, req.MsgId, req.ViewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &dataview_chat_api.UpdateMsgResponse{
			Code:   dataview_chat_api.UpdateMsgResponse_CODE_NO_MSG,
			ErrMsg: "聊天消息不存在",
		}, nil
	}

	msgItem, err := dao.MsgDataDao.Get(ctx, req.MsgId)
	if err != nil {
		return &dataview_chat_api.UpdateMsgResponse{
			Code:   dataview_chat_api.UpdateMsgResponse_CODE_NO_MSG,
			ErrMsg: "聊天消息不存在",
		}, nil
	}

	if msgItem.CreateUserId != sessionItem.UserId {
		return &dataview_chat_api.UpdateMsgResponse{
			Code:   dataview_chat_api.UpdateMsgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = dao.MsgDataDao.Update(sessCtx, req.MsgId, req.Content)
		if err != nil {
			return nil, err
		}
		return &dataview_chat_api.UpdateMsgResponse{
			Code: dataview_chat_api.UpdateMsgResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}

	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.UpdateChatMsgNotice{
		ProjectId: req.ProjectId,
		ViewId:    req.ViewId,
		MsgId:     req.MsgId,
	})
	return ret.(*dataview_chat_api.UpdateMsgResponse), nil
}

func (apiImpl *DataViewChatApiImpl) GetMsg(ctx context.Context, req *dataview_chat_api.GetMsgRequest) (*dataview_chat_api.GetMsgResponse, error) {
	emptyInfo := &dataview_chat_api.ChatMsgInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &dataview_chat_api.GetMsgResponse{
			Code:   dataview_chat_api.GetMsgResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Msg:    emptyInfo,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &dataview_chat_api.GetMsgResponse{
			Code:   dataview_chat_api.GetMsgResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
			Msg:    emptyInfo,
		}, nil
	} else if err == utils.ErrNoRole {
		return &dataview_chat_api.GetMsgResponse{
			Code:   dataview_chat_api.GetMsgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Msg:    emptyInfo,
		}, nil
	} else if err != nil {
		return nil, err
	}

	exist, err := dataview_dao.ViewDao.Exist(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &dataview_chat_api.GetMsgResponse{
			Code:   dataview_chat_api.GetMsgResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
			Msg:    emptyInfo,
		}, nil
	}

	exist, err = dataview_dao.ChatMsgIndexDao.Exist(ctx, req.MsgId, req.ViewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &dataview_chat_api.GetMsgResponse{
			Code:   dataview_chat_api.GetMsgResponse_CODE_NO_MSG,
			ErrMsg: "聊天消息不存在",
			Msg:    emptyInfo,
		}, nil
	}

	msgItem, err := dao.MsgDataDao.Get(ctx, req.MsgId)
	if err != nil {
		return &dataview_chat_api.GetMsgResponse{
			Code:   dataview_chat_api.GetMsgResponse_CODE_NO_MSG,
			ErrMsg: "聊天消息不存在",
			Msg:    emptyInfo,
		}, nil
	}

	userItemList, err := user_dao.UserInfoDao.ListById(ctx, []string{msgItem.CreateUserId})
	if err != nil {
		return nil, err
	}
	msg := &dataview_chat_api.ChatMsgInfo{
		MsgId:      msgItem.MsgId,
		Content:    msgItem.Content,
		SendUserId: msgItem.CreateUserId,
		SendTime:   msgItem.CreateTime,
		HasChanged: msgItem.HasChanged,
	}
	if len(userItemList) > 0 {
		msg.SendDisplayName = userItemList[0].BasicInfo.DisplayName
		msg.SendLogoUri = userItemList[0].BasicInfo.LogoUri
	}
	return &dataview_chat_api.GetMsgResponse{
		Code: dataview_chat_api.GetMsgResponse_CODE_OK,
		Msg:  msg,
	}, nil
}
